﻿/********************************************************************************
    Copyright (C) Binod Nepal, Planet Earth Solutions Pvt. Ltd., Kathmandu.
	Released under the terms of the GNU General Public License, GPL, 
	as published by the Free Software Foundation, either version 3 
	of the License, or (at your option) any later version.
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
    See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
***********************************************************************************/

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Transactions;
using Pes.Utility;
using System.Text;
using System.Net;

namespace MixNP.Web.Classifieds
{

    public partial class Sell : MixNP.BusinessLayer.BaseClass
    {
        int categoryId;
        double itemId;
        string categoryAlias;
        string categoryName;

        string title;
        string priceType;
        string price;
        string details;

        List<KeyValuePair<string, string>> otherFields;

        protected override void OnInit(EventArgs e)
        {
            this.RequiresLogin = true;
            base.OnInit(e);
        }
        
        private void SetValues()
        {
            categoryAlias = Conversion.TryCastString(RouteData.Values["alias"]);
            itemId = Conversion.TryCastDouble(RouteData.Values["item-id"]);
            categoryId = MixNP.BusinessLayer.Categories.GetCategoryId(categoryAlias);
            categoryName = MixNP.BusinessLayer.Categories.GetCategoryName(categoryId);
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            this.SetValues();

            if (!string.IsNullOrWhiteSpace(Conversion.TryCastString(RouteData.Values["item-id"])))
            {
                if (itemId == double.MinValue)
                {
                    MixNP.BusinessLayer.Helpers.PageHelper.ContentNotFound(Context);
                    return;
                }
            }

            if (categoryId == int.MinValue)
            {
                MixNP.BusinessLayer.Helpers.PageHelper.ContentNotFound(Context);
                return;
            }

            this.SeoOptimization(categoryName, categoryAlias);


            if (itemId > 0)
            {
                using (DataTable table = MixNP.BusinessLayer.Items.GetItem(itemId))
                {
                    if (table.Rows.Count == 1)
                    {
                        DataRow row = table.Rows[0];
                        title = Conversion.TryCastString(row["Title"]);
                        priceType = Conversion.TryCastString(row["PriceType"]);
                        price = Conversion.TryCastString(row["Price"]);
                        details = Conversion.TryCastString(row["Details"]);
                        WdmTextBox.Text = details;
                        WdmTextBox.Rows = 10;
                    }
                    else
                    {
                        MixNP.BusinessLayer.Helpers.PageHelper.ContentNotFound(Context);
                        return;
                    }
                }
            }

            if (IsPostBack)
            {
                string method = Conversion.TryCastString(Request.Form["__EVENTTARGET"]);
                string argument = Conversion.TryCastString(Request.Form["__EVENTARGUMENT"]);

                if (method.Equals("DeleteFile"))
                {
                    MixNP.BusinessLayer.Items.DeleteItemImage(argument);
                }
            }

            this.LoadControls();
            this.LoadControlsFromDatabase(categoryId);
            this.DisplayImages();

            otherFields = this.GetOtherFields();

            if (otherFields.Count == 0)
            {
                this.LoadOtherFields();
            }
            else
            {
                this.LoadOtherFields(otherFields);
            }
        }

        private void LoadOtherFields()
        {
            using (DataTable otherFields = MixNP.BusinessLayer.Items.GetOtherFields(itemId))
            {
                if (otherFields.Rows.Count > 0)
                {
                    List<KeyValuePair<string, string>> fields = new List<KeyValuePair<string, string>>();
                    string name = string.Empty;
                    string value = string.Empty;

                    foreach (DataRow fieldRow in otherFields.Rows)
                    {
                        name = Conversion.TryCastString(fieldRow["FieldName"]);
                        value = Conversion.TryCastString(fieldRow["FieldValue"]);

                        fields.Add(new KeyValuePair<string, string>(name, value));
                    }

                    LoadOtherFields(fields);
                }
            }
        }

        protected void AsyncLinkButton_Click(object sender, EventArgs e)
        {

        }

        private void DisplayImages()
        {
            using (DataTable table = MixNP.BusinessLayer.Items.GetImages(itemId))
            {
                if (table.Rows.Count > 0)
                {
                    StringBuilder html = new StringBuilder();
                    string filePath = string.Empty;

                    html.Append("<ul class=\"bpad8 thumb\">");

                    foreach (DataRow row in table.Rows)
                    {
                        filePath = ResolveUrl("~/Handlers/GetItemImage.ashx?Path=" + Conversion.TryCastString(row["FilePath"]));

                        html.Append("<li>");
                        html.Append("<a style='cursor:pointer' href=\"javascript:deleteImage('" + Conversion.TryCastString(row["FilePath"]) + "')\">");
                        html.Append("<img src='" + filePath + "&W=172&H=172' />");
                        html.Append("</a>");
                        html.Append("</li>");
                    }

                    html.Append("</ul>");

                    ImageLiteral.Text = html.ToString();
                }
            }
        }

        private void SeoOptimization(string categoryName, string categoryAlias)
        {
            CategoryNameLiteral.Text = categoryName;

            this.Page.Title = "Kathmandu Classifieds. Sell " + categoryName;
            this.Page.MetaKeywords = "kathmandu, nepal, MixNP, classifieds, sell, " + categoryAlias;
            this.Page.MetaDescription = "Sell " + categoryAlias + " in Kathmandu on mixnp.com";
        }

        private void LoadControls()
        {
            MixNP.Web.ServiceLayer.ControlManager.AddTextBox("TitleTextBox", "Title", "Text", 46, -1, true, string.Empty, "textbox wide", "Write a short, descriptive, and honest title. The title must identify the product or service you are trying to sell.", title, false, 100, this.Page, this.placeholder);
            MixNP.Web.ServiceLayer.ControlManager.AddListControl("PriceTypeRadioButtonList", "Price Type", "Price Not Applicable=0, Price is Negotiable=1, Price is Non Negotiable=-1", "1", true, "Select the best price type which applies to this item.", priceType, false, "RadioButton List", 200, this.Page, this.placeholder);
            MixNP.Web.ServiceLayer.ControlManager.AddTextBox("PriceTextBox", "Price", "Decimal", 32, -1, false, string.Empty, "textbox range", "", price, false, 300, this.Page, this.placeholder);
        }

        private void LoadControlsFromDatabase(int categoryId)
        {
            using (DataTable table = MixNP.BusinessLayer.Categories.GetCustomFields(categoryId))
            {
                if (table.Rows.Count > 0)
                {
                    foreach (DataRow row in table.Rows)
                    {
                        string customFieldId = row["CustomFieldId"].ToString();
                        string fieldLabel = row["FieldLabel"].ToString();
                        string fieldType = row["FieldTypeName"].ToString();
                        string regex = row["RegularExpression"].ToString();
                        string note = row["Note"].ToString();
                        string cssClass = row["CssClass"].ToString();
                        int maxLength = Conversion.TryCastInteger(row["MaxLength"]);
                        short fieldOrder = Conversion.TryCastShort(row["FieldOrder"]);
                        double maxValue = Conversion.TryCastInteger(row["MaxValue"]);
                        string list = row["List"].ToString();
                        string initialValue = row["InitialValue"].ToString();

                        if (itemId > 0)
                        {
                            initialValue = MixNP.BusinessLayer.Categories.GetCustomFieldValue(itemId, Conversion.TryCastInteger(customFieldId));
                        }

                        bool isExpression = Conversion.TryCastBoolean(row["IsExpression"]);
                        bool fieldRequired = Conversion.TryCastBoolean(row["FieldRequired"]);

                        switch (fieldType.ToLower())
                        {
                            case "memo (long text)":
                            case "money":
                            case "date":
                            case "integer":
                            case "integer range":
                            case "money range":
                            case "date range":
                            case "text":
                            case "url":
                            case "email":
                                MixNP.Web.ServiceLayer.ControlManager.AddTextBox("TextBox" + customFieldId, fieldLabel, fieldType, maxLength, maxValue, fieldRequired, regex, cssClass, note, initialValue, isExpression, fieldOrder, this.Page, this.customPlaceholder);
                                break;
                            case "combobox list":
                            case "radiobutton list":
                            case "checkbox list":
                                MixNP.Web.ServiceLayer.ControlManager.AddListControl("ListControl" + customFieldId, fieldLabel, list, initialValue, fieldRequired, note, cssClass, isExpression, fieldType, fieldOrder, this.Page, this.customPlaceholder);
                                break;
                        }
                    }
                }
            }
        }

        private List<KeyValuePair<string, string>> GetCustomFields(int categoryId)
        {
            List<KeyValuePair<string, string>> fields = new List<KeyValuePair<string, string>>();

            using (DataTable table = MixNP.BusinessLayer.Categories.GetCustomFields(categoryId))
            {
                if (table.Rows.Count > 0)
                {
                    foreach (DataRow row in table.Rows)
                    {
                        string customFieldId = row["CustomFieldId"].ToString();
                        string fieldLabel = row["FieldLabel"].ToString();
                        string fieldType = row["FieldTypeName"].ToString();
                        string regex = row["RegularExpression"].ToString();
                        string note = row["Note"].ToString();
                        string cssClass = row["CssClass"].ToString();
                        int maxLength = Conversion.TryCastInteger(row["MaxLength"]);
                        short fieldOrder = Conversion.TryCastShort(row["FieldOrder"]);
                        double maxValue = Conversion.TryCastInteger(row["MaxValue"]);
                        string list = row["List"].ToString();
                        string initialValue = row["InitialValue"].ToString();

                        bool isExpression = Conversion.TryCastBoolean(row["IsExpression"]);
                        bool fieldRequired = Conversion.TryCastBoolean(row["FieldRequired"]);
                        string controlId = string.Empty;
                        string value = string.Empty;

                        switch (fieldType.ToLower())
                        {
                            case "memo (long text)":
                            case "money":
                            case "date":
                            case "integer":
                            case "text":
                            case "url":
                            case "email":
                                controlId = "TextBox" + customFieldId;
                                value = MixNP.BusinessLayer.Helpers.RequestForm.GetUserControlFormValue(controlId, this.Page);

                                if (fieldType.ToLower().Equals("url"))
                                {
                                    value = Pes.Utility.PageUtility.CleanUrl(value);
                                }
                                
                                break;
                            case "integer range":
                            case "money range":
                            case "date range":
                                controlId = "TextBox" + customFieldId;
                                value = MixNP.BusinessLayer.Helpers.RequestForm.GetUserControlFormValue(controlId, this.Page);
                                value += "," + MixNP.BusinessLayer.Helpers.RequestForm.GetUserControlFormRangeValue(controlId, this.Page);
                                break;
                            case "combobox list":
                            case "radiobutton list":
                                controlId = "ListControl" + customFieldId;
                                value = MixNP.BusinessLayer.Helpers.RequestForm.GetUserControlFormValue(controlId, this.Page);
                                break;
                            case "checkbox list":
                                controlId = "ListControl" + customFieldId;
                                value = MixNP.BusinessLayer.Helpers.RequestForm.GetUserControlFormCheckBoxSelection(controlId, this.Page);
                                break;
                        }

                        if (!string.IsNullOrWhiteSpace(value))
                        {
                            fields.Add(new KeyValuePair<string, string>(customFieldId, value));
                        }
                    }
                }
            }

            return fields;
        }

        private List<KeyValuePair<string, string>> GetOtherFields()
        {
            List<KeyValuePair<string, string>> retVal = new List<KeyValuePair<string, string>>();

            foreach (string key in this.Page.Request.Form.Keys)
            {
                if (key.StartsWith("extrafield"))
                {
                    if (Conversion.TryCastInteger(key.Replace("extrafield", "")) > 0)
                    {
                        KeyValuePair<string, string> field = new KeyValuePair<string, string>(this.Page.Request.Form[key], this.Page.Request.Form[key + "-value"]);
                        retVal.Add(field);
                    }
                }
            }

            return retVal;
        }

        protected void CustomValidator1_Validate(object sender, ServerValidateEventArgs args)
        {
            IEnumerable<IGrouping<string, KeyValuePair<string, string>>> duplicateKVPsByKey = otherFields.GroupBy(kvp => kvp.Key).Where(g => g.Count() > 1);
            if (duplicateKVPsByKey.Count() > 0)
            {
                args.IsValid = false;
                CustomValidator1.Text = "Please remove the duplicate title.<br />";
                LoadOtherFields(otherFields);
                return;
            }

            args.IsValid = true;
        }

        private void LoadOtherFields(List<KeyValuePair<string, string>> fields)
        {
            string names = string.Empty;
            string values = string.Empty;

            foreach (KeyValuePair<string, string> field in fields)
            {
                if (!string.IsNullOrWhiteSpace(names))
                {
                    names += "++--++-MixNP-++--++";
                    values += "++--++-MixNP-++--++";
                }

                names += field.Key;
                values += field.Value;
            }
            Pes.Utility.PageUtility.ExecuteJavaScript("addOtherFields", "jQuery(document).ready(function () { addOtherFields('" + names + "', '" + values + "'); });", this.Page);
        }

        private void SendAlert(double itemId)
        {
            string emailBody = System.IO.File.ReadAllText(this.Page.Server.MapPath("~/Classifieds/Templates/ItemAdded.htm"));
            using (System.Data.DataTable itemTable = MixNP.BusinessLayer.Items.GetItem(itemId))
            { 
                if(itemTable.Rows.Count.Equals(1))
                {
                    System.Data.DataRow row = itemTable.Rows[0];
                    string title = Conversion.TryCastString(row["Title"]);
                    decimal price = Conversion.TryCastDecimal(row["Price"]);
                    string details = Conversion.TryCastString(row["Details"]);
                    short cityId = Conversion.TryCastShort(row["CityId"]);

                    string link = string.Empty;
                    string image = string.Empty;

                    if (!price.Equals(0))
                    {
                        title += " for Rs. " + price.ToString("G29");
                    }

                    details = MixNP.BusinessLayer.Helpers.MarkdownTransformer.Transform(details);

                    link = MixNP.BusinessLayer.Items.GetItemUrl(itemId, this.Page);

                    link = "<a href='" + link + "' title='" + title + "'>" + link + "</a>";

                    using (System.Data.DataTable imageTable = MixNP.BusinessLayer.Items.GetImages(itemId))
                    {
                        if (imageTable.Rows.Count > 0)
                        {
                            foreach (DataRow imageRow in imageTable.Rows)
                            {
                                string path = Conversion.TryCastString(imageRow["FilePath"]);
                                image += "<img src='" + "http://" + Request.Url.Authority + ResolveUrl("~/Handlers/GetItemImage.ashx?W=172&H=172&Path=" + path) + "' style='border:1px solid #E0E0E0; padding:4px;margin:4px;float:left;' />";
                            }
                            image += "<div style='clear:both;' />";
                        }
                    }

                    emailBody = emailBody.Replace("{Title}", title);
                    emailBody = emailBody.Replace("{Details}", details);
                    emailBody = emailBody.Replace("{Image}", image);
                    emailBody = emailBody.Replace("{Link}", link);

                    using (DataTable alertTable = MixNP.BusinessLayer.Alerts.AlertMe.GetAlert(categoryId, cityId, price))
                    {
                        foreach (DataRow alertRow in alertTable.Rows)
                        {
                            string recipient = Conversion.TryCastString(alertRow["EmailAddress"]);
                            MixNP.BusinessLayer.Email.SendEmail("MixNP.Alerts.AlertMe", itemId.ToString(), recipient, title, emailBody, "noreply@mixnp.com");
                        }

                        MixNP.BusinessLayer.Email.ProcessEmails();
                    }
                }
            }
        }
        
        protected void SaveButton_Click(object sender, EventArgs e)
        {
            CustomValidator1.Validate();
            this.Validate();
            if (!this.IsValid) { return; }
            var transactionOptions = new TransactionOptions();
            transactionOptions.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;
            transactionOptions.Timeout = TransactionManager.MaximumTimeout;
            
            double itemIdentity = double.MinValue;


            try
            {
                this.SetValues();
                using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, transactionOptions))
                {
                    string emailAddress = User.Identity.Name;
                    string name = MixNP.BusinessLayer.Users.GetNameFromEmailAddress(emailAddress);
                    string title = MixNP.BusinessLayer.Helpers.RequestForm.GetUserControlFormValue("TitleTextBox", this.Page);
                    decimal price = Conversion.TryCastDecimal(MixNP.BusinessLayer.Helpers.RequestForm.GetUserControlFormValue("PriceTextBox", this.Page));
                    short priceType = Conversion.TryCastShort(MixNP.BusinessLayer.Helpers.RequestForm.GetUserControlFormValue("PriceTypeRadioButtonList", this.Page));
                    string details = WdmTextBox.Text;

                    if (itemId.Equals(double.MinValue))
                    {
                        itemIdentity = MixNP.BusinessLayer.Items.SaveItem(categoryId, emailAddress, name, title, price, priceType, details, this.GetCustomFields(categoryId), this.GetOtherFields());
                    }
                    else
                    {
                        MixNP.BusinessLayer.Items.UpdateItem(itemId, categoryId, title, price, priceType, details, this.GetCustomFields(categoryId), this.GetOtherFields());
                        itemIdentity = itemId;
                    }

                    if (itemIdentity > 0)
                    {
                        if (FileUpload1.HasFile) { SaveImage(itemIdentity, FileUpload1); }
                        if (FileUpload2.HasFile) { SaveImage(itemIdentity, FileUpload2); }
                        if (FileUpload3.HasFile) { SaveImage(itemIdentity, FileUpload3); }
                        if (FileUpload4.HasFile) { SaveImage(itemIdentity, FileUpload4); }
                        if (FileUpload5.HasFile) { SaveImage(itemIdentity, FileUpload5); }
                        if (FileUpload6.HasFile) { SaveImage(itemIdentity, FileUpload6); }
                        if (FileUpload7.HasFile) { SaveImage(itemIdentity, FileUpload7); }
                        if (FileUpload8.HasFile) { SaveImage(itemIdentity, FileUpload8); }
                        if (FileUpload9.HasFile) { SaveImage(itemIdentity, FileUpload9); }
                        if (FileUpload10.HasFile) { SaveImage(itemIdentity, FileUpload10); }
                        if (FileUpload11.HasFile) { SaveImage(itemIdentity, FileUpload11); }
                        if (FileUpload12.HasFile) { SaveImage(itemIdentity, FileUpload12); }
                        if (FileUpload13.HasFile) { SaveImage(itemIdentity, FileUpload13); }
                        if (FileUpload14.HasFile) { SaveImage(itemIdentity, FileUpload14); }
                        if (FileUpload15.HasFile) { SaveImage(itemIdentity, FileUpload15); }
                        if (FileUpload16.HasFile) { SaveImage(itemIdentity, FileUpload16); }
                        if (FileUpload17.HasFile) { SaveImage(itemIdentity, FileUpload17); }
                        if (FileUpload18.HasFile) { SaveImage(itemIdentity, FileUpload18); }
                        if (FileUpload19.HasFile) { SaveImage(itemIdentity, FileUpload19); }
                        if (FileUpload20.HasFile) { SaveImage(itemIdentity, FileUpload20); }

                    }

                    if (itemId.Equals(double.MinValue))
                    {
                        SendAlert(itemIdentity);
                        scope.Complete();
                    }
                }
            }
            catch
            {
                LoadOtherFields(this.GetOtherFields());
                CustomErrorLiteral.Text = "We are sorry but we could not save this item at this time. The site administrator has been notified about this error and will take necessary actions to fix it.";
            }


            string url = MixNP.BusinessLayer.Items.GetItemUrl(itemIdentity, this.Page);

            Response.Redirect(url, true);
        }

        private void SaveImage(double itemId, FileUpload control)
        {
            string path = Guid.NewGuid().ToString() + System.IO.Path.GetExtension(control.FileName);
            string filePath = "~/Classifieds/Images/Static/" + path;

            if (control.HasFile)
            {
                try
                {
                    control.PostedFile.SaveAs(Server.MapPath(filePath));
                    MixNP.BusinessLayer.Items.SaveItemImage(itemId, path);
                }
                catch
                {
                    System.IO.File.Delete(filePath);
                    throw;
                }
            }
        }

    }

}

